package com.atzly.community.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 创建数据源
 */
//@Component("dataSourceBuilder")
public class DataSourceBuilder {
  private static final Logger logger = LoggerFactory.getLogger(DataSourceBuilder.class);

  private static final int DEFAULT_INITIAL_SIZE = 50;
  private static final int DEFAULT_MIN_IDLE = 10;
  private static final int DEFAULT_MAX_ACTIVE = 400;
  private static final long DEFAULT_MAX_WAIT = 60000L;
  private static final long DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS = 6000L;
  private static final long DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 30000L;
  private static final String DEFAULT_VALIDATION_QUERY = "SELECT '1'";
  private static final boolean DEFAULT_TEST_WHILE_IDLE = true;
  private static final boolean DEFAULT_TEST_ON_BORROW = true;
  private static final boolean DEFAULT_TEST_ON_RETURN = false;
  private static final boolean DEFAULT_POOL_PREPARED_STATEMENTS = false;
  private static final int DEFAULT_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE = 20;
  private static final String DEFAULT_MYSQL_FILTERS = "config";  // stat,log4j
  private static final String DEFAULT_CLICKHOUSE_FILTERS = "config";  // stat,log4j
  private static final String DEFAULT_CONNECTION_PROPERTIES = "config.decrypt=false";

  /**
   * 生成数据源
   * @param dataSourceConfig
   * @return
   */
  public DataSource build(DataSourceConfig dataSourceConfig) {
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setUrl(dataSourceConfig.getUrl());
    dataSource.setUsername(dataSourceConfig.getUsername());
    dataSource.setPassword(dataSourceConfig.getPassword());

    if (dataSourceConfig.getDriverClassName() != null) {
//      dataSource.setDriverClassName(dataSourceConfig.getDriverClassName());
//      dataSource.setDriver(new ClickHouseDriver());
    }
    if (dataSourceConfig.getInitialSize() == null) {
      dataSource.setInitialSize(DEFAULT_INITIAL_SIZE);
    } else {
      dataSource.setInitialSize(dataSourceConfig.getInitialSize());
    }
    if (dataSourceConfig.getMinIdle() == null) {
      dataSource.setMinIdle(DEFAULT_MIN_IDLE);
    } else {
      dataSource.setMinIdle(dataSourceConfig.getMinIdle());
    }
    if (dataSourceConfig.getMaxActive() == null) {
      dataSource.setMaxActive(DEFAULT_MAX_ACTIVE);
    } else {
      dataSource.setMaxActive(dataSourceConfig.getMaxActive());
    }

    dataSource.setMaxWait(DEFAULT_MAX_WAIT);
    dataSource.setTimeBetweenEvictionRunsMillis(DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
    dataSource.setMinEvictableIdleTimeMillis(DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
    dataSource.setValidationQuery(DEFAULT_VALIDATION_QUERY);
    dataSource.setTestWhileIdle(DEFAULT_TEST_WHILE_IDLE);
    dataSource.setTestOnBorrow(DEFAULT_TEST_ON_BORROW);
    dataSource.setTestOnReturn(DEFAULT_TEST_ON_RETURN);

    // 超过时间限制是否回收
    // dataSource.setRemoveAbandoned(true);
    // 超时时间；单位为秒。180秒=3分钟
    // dataSource.setRemoveAbandonedTimeout(180);
    // 关闭abanded连接时输出错误日志 
    // dataSource.setLogAbandoned(true);
    
    dataSource.setPoolPreparedStatements(DEFAULT_POOL_PREPARED_STATEMENTS);
    dataSource.setMaxPoolPreparedStatementPerConnectionSize(DEFAULT_MAX_POOL_PREPARED_STATEMENT_PER_CONNECTION_SIZE);

    try {
      if (dataSourceConfig.getUrl().contains("clickhouse")) {
        dataSource.setFilters(DEFAULT_CLICKHOUSE_FILTERS);
      }else {
        dataSource.setFilters(DEFAULT_MYSQL_FILTERS);
      }
    } catch (SQLException e) {
      logger.warn("set filters error", e);
    }
    
    dataSource.setConnectionProperties(DEFAULT_CONNECTION_PROPERTIES);
    logger.info(" build datasource {}", dataSourceConfig);
    return dataSource;
  }

  /**
   * 批量生成数据源（一般针对主从，也可生成一个数据源）
   * @param arrayDataSourceConfig
   * @return
   */
  public ArrayDataSource buildArrayDataSource(ArrayDataSourceConfig arrayDataSourceConfig) {
//
//    if (DataSourceConfigManager.CLICKHOUSE_DB_ID.equals(arrayDataSourceConfig.getDynamicName())) {
//      return buildCkArrayDataSource(arrayDataSourceConfig);
//    }

    List<DataSourceConfig> dataSourceConfigs = arrayDataSourceConfig.getDataSourceConfigs();
    List<DataSource> dataSources = new ArrayList<>();
    for (DataSourceConfig dataSourceConfig : dataSourceConfigs) {
      DataSource dataSource = build(dataSourceConfig);
      dataSources.add(dataSource);
    }
    return new ArrayDataSource(dataSources);
  }
//  /**
//   * 批量生成数据源（一般针对主从，也可生成一个数据源）
//   * @param arrayDataSourceConfig
//   * @return
//   */
//  public ArrayDataSource buildCkArrayDataSource(ArrayDataSourceConfig arrayDataSourceConfig) {
//    List<DataSourceConfig> dataSourceConfigs = arrayDataSourceConfig.getDataSourceConfigs();
//    List<DataSource> dataSources = new ArrayList<>();
//    for (DataSourceConfig dataSourceConfig : dataSourceConfigs) {
//      ClickHouseDataSource clickHouseDataSource = new ClickHouseDataSource(dataSourceConfig.getUrl() );
//      dataSources.add(clickHouseDataSource);
//    }
//    return new ArrayDataSource(dataSources);
//  }
}
